craftstudiofandomcom-20200213-history
Tutorials/Sneak peek at Lua for experienced programmers
This tutorial is intended for already experienced programmers. It outlines the mains features of Lua and its major differences with other programming languages. You may also check out this file (.pdf) or the official tutorials. Main No semi colon at the end of instructions. A one line comment begins by two hyphens : --. A multiline block of comment is wrapped by these tags : -- -- You may nest comment blocks by adding one or several equal sign(s) between the brackets. --[[ this is --[=[ a multiline ]=]-- comment ]]-- Use the print(whatever) ''function to print text in the console. It can display several values at a time (without being concatenated) if they are separated by a coma. print(value1, value2, value3) -- will display the 3 values on the same line with a decent space between each Variables are dynamicaly typed and function have no return type. Declaring a variable (see below for functions) : variableName = value You may set the value of several variables at a time, but be aware that the syntax is not the same as in other languages : variable1, variable2, variable3 = value1, value2, value3 -- variable1 is equal to value1, variable2 is equal to value2 and variable3 is equal to value3 There is only 7 data types : String, Number, Boolean, Table, Function, UserData and Thread. When a variable does not exist or does not contains any value, which is the same in Lua, its value is ''nil (equivalent to null). The type(exp) ''function returns the type of the expression as a lowercase string. The ''error(message) function displays the error message in the console and kill the script. Strings You may use simple or double quotation marks when the string is on a single line. You may escape characters in strings only when they are on a single line. You may write a string on several lines by wrapping it with double square brackets but you can not escape characters with this syntax. You can nest multiline strings by adding one or several equal signs between the brackets. this is a string written on several lignes Concatenation uses two dots .. : "a concatened " .. 'string' Numbers are coerced (automaticaly casted) into strings when needed, for display or concatenation for instance. That is not the case with boolean, which require the use of the tostring() function. "100"..100 -- is equivalent to "100100" "this is "..tostring(true) -- "this is true" The length of a string is given by the sharp operator when placed just in front of the string. text = "a string" print(#text) -- will print 8 Numbers This sole type for any numerical data. Power of 10 : 1.2345e6 -- 1234500 543.21E8 -- 54321000000 2.56e-4 -- 0.000256 The tonumber(string)''function convert from string to number but only if the string contains only numbers, - or + in front of a number, . and/or e. Using an arithmetic operator with a string and a number will try to cast the string into a number : "100"+100 -- 200. Operators +=, -=, *=, /=, ++ and -- '''do not exist'. Only +, -, *, /, % and ^ exist. Loops while condition do block end repeat block until condition for variable = start, end, step do block end step is optionnal and equal to 1 by default. Check out the Tables section below for a more advanced use of the for() loop with tables and pairs() and ipairs() iterators. A loop can be stopped with break, but continue does not exists. Conditions if condition then block elif condition then block else block end elif and else are optionnal. No ternary operator. Comparison operators : , ~= (equivalent to !=), <, <=, >, >=, not (!), and (&&), or (||). Operators and ~ does not exist. < and > works with strings : ("abc" < "def") is true. Everything that is not false nor nil is true. Consequentely 0 or empty strings are equivalent to true. Also, false is equivalent to nil, but (false nil) is false and (not nil) is true. Comparisons on tables or functions actually compare the memory address, not the content. t = {} t2 = t (t t2) is true because t and t2 are referencing''the same table. {} {} is false because those are two different tables. (t {}) or (t2 {}) are also false. The comparison operators do not cast types : ("10" 10) is false but (tonumber("10") 10) is true. ''And and or''operators do not behave in the same way as in other languages. (exp1 and exp2) do not necessarily return a boolean. And returns the left value if it is equivalent to false, or returns the right value. Or does the opposite, it returns the left value if it is equivalent to true, or returns the right value. Tables Tables are flexible collections, they may contain any data type as key or as value. '''Numerical indexes begin at 1 and not at 0 !' myTable = { 5, "string", false} print(myTable1) -- 5 print(myTable4) -- nil Adding a value at the end of a table : table.insert(tableName, value) -- the function does not return the new table, it works on the table by reference table is the name of the global variable provided by Lua that stores all functions related to tables. Inserting a value at an index, without overriding the value that may already exist at this index by incrementing the index of the other value : table.insert(tableName, index, value) Removing a value from an index while decrementing the index of the other values : table.remove(tableName, index) Deleting a value without modifying the index of the other values : tableNameindex = nil Non-numerical key must not begin by a number. There is two syntaxes when the key is a string : myTable = { with space" = value, keyWithoutSpace = value } myTablewith space" myTable.keyWithoutSpace -- or myTable"keyWithoutSpace" You may also use the square brackets with numbers : myTable = { 2 = value } -- prevent the value from being assigned to the index 1 You must use the ipairs() iterator to loop on numerical keys : for key,value in ipairs(tableName) do print(key, value) end -- or for key=1, #tableName do -- #tableName returns the table's size (see below) print(key, tableNamekey) end Warning ! The # operator, when used with tables does not necessarily returns the number of keys whose values are non-nil. You must use the pairs() iterator to loop on all keys : for key,value in pairs(tableName) do print(key, value) end Functions Function is a data type. Named functions are just a variable that contains a function. function AFunction() block end -- is the same as AFunction = function() block end -- you can also use anonymous functions var = (function(n) return n*2 end)(4) -- var is equal to 8 In Lua, a function can't be overloaded and arguments can't have a default value or type. But functions may have a variable number of arguments if the last argument is 3 dots : function(arg1, ...). You can then access the arg table from within the function which contains all optionnal arguments. function AFunction(...) print(unpack(arg)) end AFunction('two', 3, 4) -- will print : two 3 4 AFunction(20, "thirty") -- 20 thirty If you call a function with too many arguments, the extra arguments will be ignored. Arguments to which you do not assign a value during a function call have the nil value inside the function. unpack() is a function that transforms a table into an expression that is equivalent to a comma separated list of values (which is not a string) : myTable = {1, 2, 3} -- unpack(myTable) is equivalent to the expression 1, 2, 3 -- setting several variables with values from the table : var1, var2, var3 = unpack(table) -- var1 is equal to 1, var2 is equal to 2 and var3 is equal to 3 AFunction(unpack(myTable), 4) -- is equivalent to AFunction(1, 2, 3, 4) A function may return a list of values : foo = function() return 1, 2, 3 end var1, var2, var3 = foo() -- var1 is equal to 1... When a function returns several values, you can get them as a table if you wrap the call to the function with curly brackets : myTable = {foo()} print(unpack(myTable)) -- 1 2 3 -- this is equivalent to myTable = {1, 2, 3} -- if you just want one value, you can write : var2 = ( {foo()} )2 -- which is equivalent to myTable2 -- if you only want the first value, wrap the function call with parenthesis : var1 = (foo()) Variable scope Two scopes : global and local. Global is the default scope. Global variables are accessible from any script within your applications (at least with CraftStudio). Local variables (prefixed with the local keyword) are accessible only from the scope there are created in as well as from any sub-scopes (just like the default behavior in other languages). Ie : a local variable created within a script will only be accessible within that script, and a local variable created within a function will not be accessible from outside the function. In CraftStudio, a third scope can be defined. Public variables are the ones created on the self variable from within a Behavior function (like Awake or Update). They are specific to an instance of the script and accessible only from one of its instances. OOP Lua has no concept of class, so there is no standard OOP. But Lua do have objects. They are tables which will typically contain at least functions and be used in an object oriented way. Object = { Function1 = function() end } Object.member = "value" -- You may create functions on objects in four different ways. The first 3 are equivalent. -- The first one is when you declare the function in the table constructor, as it has been done above. -- The second one : Object.Function2 = function() end -- The third one : function Object.Function3() end -- And the fourth one : -- Note the colon between the object's and function's names function Object:Function4() -- self end Using the colon will create the self variable inside the function. But be advised that self does not necessarily represent the object. Self will have the value of the first argument, which depends on how the function is called. Calling a function with a colon between the object's name and the function's name will put the object as the first argument, moving back the others arguments : function Object:Function(arg1, arg2) end -- is the same as function Object.Function(self, arg1, arg2) end Object:Function("arg1", "arg2") -- is the same as Object.Function(Object, "arg1", "arg2") Self is the object if and only if the function is created and called using a colon. When it comes to objects and functions, it's a good practice to always use a colon. Metamethods and Metatables Metamethods are Lua's magic methods, used for operator overloading or with metatables. A metatable is a table used by being applied(and not joined in) to other regular tables/objects. A modification of a metatable is applied instanly to every tables on which the metatable has been applied. That's why metatbles will mostly be used to store static data as functions. Metamethods and metables allow to simulate classic object oriented behaviors (like inheritance) to some extend. For more infos on these advanced subjects, please read the official tutorials.